package com.spring.cloud.eurekaclientzuul.filter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import io.github.resilience4j.ratelimiter.RateLimiter;
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
import io.vavr.control.Try;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.spring.cloud.commonutils.vo.UserInfo;
import com.spring.cloud.commonutils.vo.ResultMessage;
import java.util.concurrent.Callable;

@Component
public class RateLimiterFilter extends ZuulFilter {

//    限速器注册机
    @Autowired
    private RateLimiterRegistry rateLimiterRegistry;

    //对用户微服务的请求正则式匹配
    private static final  String USER_PRE = "/u/";

    //过滤器类型
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override   //过滤器排序
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER+30;
    }

    @Override
    public boolean shouldFilter() {
        //获取请求上下文
        RequestContext ctx = RequestContext.getCurrentContext();
        //获取URI
        String uri = ctx.getRequest().getRequestURI();
        //判断uri 开头 是否是 /u/开头
        return uri.startsWith(USER_PRE);
    }

    @Override
    public Object run() throws ZuulException {

        //获取限速器
        RateLimiter rateLimiter = rateLimiterRegistry.rateLimiter("user");
        //限速器逻辑
        Callable<ResultMessage> call1 = ()-> new ResultMessage(true,"通过");
        //绑定限速器
        Callable<ResultMessage> call2 = RateLimiter.decorateCallable(rateLimiter,call1);
        //尝试获取结果
        Try<ResultMessage> tryResult = Try.of(()->call2.call())
                //降级逻辑
                .recover(ex->
                        new ResultMessage(false,"超时所限流量")
                );

        ResultMessage result = tryResult.get();
        //如果成功则在限流范围内,放行服务
        if(result.isSuccess()){
            return null;
        }
        //获取请求上下文
        RequestContext ctx = RequestContext.getCurrentContext();
        //不再进行下一步的路由,而是到此为止
        ctx.setSendZuulResponse(false);
        //设置响应码为400-坏请求
        ctx.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());

       //设置响应类型
        ctx.getResponse().setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
        //转换为JSON字符串
        ObjectMapper mapper = new ObjectMapper();
        String body = null;
        try{

            body = mapper.writeValueAsString(result);
        }catch (JsonProcessingException ex){
            ex.printStackTrace();
        }
        //设置响应体
        ctx.setResponseBody(body);
        return null;
    }
}
